/*
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.spice.servlet.inject.strategy;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import org.spice.servlet.core.components.ClassAttribute;
import org.spice.servlet.core.components.ComponentFactory;
import org.spice.servlet.core.components.DeclaredMethods;
import org.spice.servlet.core.components.Fields;
import org.spice.servlet.core.components.Interfaces;
import org.spice.servlet.dispatcher.handler.SpiceSingleton;
import org.spice.web.components.Dao;
import org.spice.web.components.Service;
import org.spice.web.components.View;
import org.spice.web.components.interceptors.Intercept;

public class ComponentImplication implements ComponentFactory{

	private 
	Class<?> clazz;
	
	private 
	Object instance;

	public 
	ComponentImplication(Class<?> clazz) {
		this.clazz = clazz;
	}

	@Override
	public 
	Boolean hasMethods() {
		final Method[] method = this.clazz.getDeclaredMethods();
		return (method.length > 0 ? Boolean.TRUE : Boolean.FALSE);
	}

	@Override
	public 
	Object instance() {
		return instance;
	}
	
	@Override
	public 
	void setInstance(final Object instance){
		this.instance = instance;
	}

	@Override
	public 
	Boolean isInterface() {
		return (this.clazz.isInterface() ? Boolean.TRUE : Boolean.FALSE);
	}

	@Override
	public 
	List<Fields> getFieldDetails() {
		final List<Fields> field = new ArrayList<Fields>();
		Field[] fields = this.clazz.getDeclaredFields();
		for(Field singleField : fields)
			field.add(new FieldInvoke(singleField));
		return field;
	}

	@Override
	public 
	List<DeclaredMethods> getDeclaredMethods() {
		final List<DeclaredMethods> declaredMethods = new ArrayList<DeclaredMethods>();
		Method[] methods = this.clazz.getDeclaredMethods();
		for(final Method method : methods){
			declaredMethods.add(new MethodsInvocation(method));
		}
		return declaredMethods;
	}

	@Override
	public 
	List<Interfaces> getDeclaredInterfaces() {
		final List<Interfaces> declaredInterfaces = new ArrayList<Interfaces>();
		Type[] types = this.clazz.getGenericInterfaces();
		for(Type type : types){
			declaredInterfaces.add(new InterfacesInvoke(type));
		}
		return declaredInterfaces;
	}

	@Override
	public 
	Boolean isWiringAllowed() {
		return (this.clazz.isAnnotationPresent(View.class)) || (this.clazz.isAnnotationPresent(Service.class)) 
		|| (this.clazz.isAnnotationPresent(Dao.class));
	}

	@Override
	public 
	ClassAttribute getClassAttribute() {
		return ClassAttribute.SINGLETON; // Can be changed in the forth coming versions.
	}

	@Override
	public 
	Boolean isInterceptor() {
		if(this.clazz.isAnnotationPresent(Intercept.class)){
			final SpiceSingleton bean = SpiceSingleton.getInstance();
			bean.setSingleIntercept(this.clazz);
		}
		return (this.clazz.isAnnotationPresent(Intercept.class));
		
	}

	@Override
	public 
	Class<?> getComponentClass() {
		return this.clazz;
	}

}
